package com.example.commontest.utils;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.URI;
import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.Future;
/**
 * @Author huaiyu yin
 * @Date 2021/6/17 3:22 下午
 * @Version 1.0
 */
public class HttpClientUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientUtil.class);

    private HttpClientUtil() {}

    public static String genUri(String... objs){
        return StringUtils.join(Arrays.asList(objs), "/");
    }

    public static String doGet(String url) {
        String result = null;
        if (null == url) {
            return result;
        }
        try {
            HttpClient httpClient = HttpClients.createDefault();
            LOGGER.info("Method: GET, Url： {}", url);
            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader("content-Type", "application/json;charset=UTF-8");
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(10000)
                    .setConnectTimeout(10000).build();
            httpGet.setConfig(requestConfig);
            HttpResponse httpResponse = httpClient.execute(httpGet);
            StatusLine statusLine = httpResponse.getStatusLine();
            int statusCode = statusLine.getStatusCode();
            LOGGER.info("StatusCode： {}", statusCode);

            if (statusCode == HttpStatus.SC_OK) {
                HttpEntity entity = httpResponse.getEntity();
                result = EntityUtils.toString(entity, "UTF-8");
                LOGGER.info("返回值是： {}", result);
            }else {
                LOGGER.info("ReasonPhrase： {}", statusLine.getReasonPhrase());
            }
        } catch (ConnectTimeoutException timeoutException) {
            LOGGER.error("调用外系统接口超时！", timeoutException);
        } catch (Exception e) {
            LOGGER.error("调用外系统接口错误！", e);
        }
        return result;
    }

    public static String postJsonData(String url, String json){
        String result = null;
        if (null == url) {
            return result;
        }
        try {
            HttpClient httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("content-Type", "application/json;charset=UTF-8");
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000)
                    .setConnectTimeout(60000).build();
            httpPost.setConfig(requestConfig);
            StringEntity stringEntity = new StringEntity(json, "UTF-8");
            httpPost.setEntity(stringEntity);
            HttpResponse response = httpClient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                result = EntityUtils.toString(response.getEntity(), "utf-8");
            }
            LOGGER.info("返回值是： {}, Response Status: {}", result, response.getStatusLine().getStatusCode());
        } catch (ConnectTimeoutException timeoutException) {
            LOGGER.error("调用外系统接口超时！", timeoutException);
        } catch (Exception e) {
            LOGGER.error("调用外系统接口错误！", e);
        }
        return result;
    }

    public static String putJsonData(String url, String json){
        String result = null;
        if (null == url) {
            return result;
        }
        try {
            HttpClient httpClient = HttpClients.createDefault();
            HttpPut httpPut = new HttpPut(url);
            httpPut.setHeader("content-Type", "application/json;charset=UTF-8");
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000)
                    .setConnectTimeout(60000).build();
            httpPut.setConfig(requestConfig);
            StringEntity stringEntity = new StringEntity(json, "UTF-8");
            httpPut.setEntity(stringEntity);
            HttpResponse response = httpClient.execute(httpPut);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                result = EntityUtils.toString(response.getEntity(), "utf-8");
                if (!Objects.equals(JSONObject.parseObject(result).getInteger("code") , HttpStatus.SC_OK)) {
                    LOGGER.error(JSONObject.parseObject(result).getString("code"));
                    for (Header header : response.getAllHeaders()) {
                        LOGGER.error(header.getName() + " : " + header.getValue());
                    }
                }
            }
            LOGGER.info("返回值是： {}, Response Status: {}", result, response.getStatusLine().getStatusCode());
        } catch (ConnectTimeoutException timeoutException) {
            LOGGER.error("调用外系统接口超时！", timeoutException);
        } catch (Exception e) {
            LOGGER.error("调用外系统接口错误！", e);
        }
        return result;
    }

    /**
     *
     * @param url img url
     * @return return new byte[]{} with error occured
     */
    public static byte[] getImgBytes(String url) {
        if (url == null) {
            return new byte[]{};
        }
        try (CloseableHttpClient client = HttpClients.createDefault()) {
            HttpGet httpGet = new HttpGet(url);
            int timeout = 5000;
            RequestConfig requestConfig = RequestConfig
                    .custom()
                    .setSocketTimeout(timeout)
                    .setConnectTimeout(timeout)
                    .setConnectionRequestTimeout(timeout)
                    .build();
            httpGet.setConfig(requestConfig);
            HttpResponse response = client.execute(httpGet);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                byte[] bytes = EntityUtils.toByteArray(entity);
                return bytes;
            }
        } catch (Exception e) {
            LOGGER.error("调用图片URL错误！", e);
        }
        return new byte[]{};
    }

    public static String getObjectsJson(String url, String token) {
        try (CloseableHttpClient client = HttpClients.createDefault()) {
            HttpGet httpGet = new HttpGet(url);
            int timeout = 50000;
            RequestConfig requestConfig = RequestConfig.custom()
                    .setSocketTimeout(timeout)
                    .setConnectTimeout(timeout)
                    .setConnectionRequestTimeout(timeout)
                    .build();
            httpGet.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
            httpGet.setConfig(requestConfig);
            HttpResponse response = client.execute(httpGet);
            String entityJson = EntityUtils.toString(response.getEntity());
            return entityJson;
        } catch (Exception e) {
            LOGGER.error("调用URL错误: {}", url, e);
            throw new RuntimeException(e);
        }
    }
/**
 * 异步请求
 */
//    public static Future<HttpResponse> getObjectsJsonAsync(String url, String token, CloseableHttpAsyncClient client) {
//        try {
//            client.start();
//            RequestConfig requestConfig = defaultRequestConfig();
//            HttpGet httpGet = new HttpGet();
//            httpGet.setURI(URI.create(url));
//            httpGet.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
//            httpGet.setConfig(requestConfig);
//
//            FutureCallback<HttpResponse> callback = generateFutureCallBack();
//            Future<HttpResponse> responseFuture = client.execute(httpGet, callback);
//            return responseFuture;
//        } catch (Exception e) {
//            LOGGER.error("异步调用URL错误: {}", url, e);
//            throw e;
//        }
//    }

    /**
     * - connectTimeout : 三次握手超时时间
     * - socketTimeout : 请求超时,传输过程中数据包之间间隔的最大时间
     * - connectionRequestTimeout : 从连接池中获取连接的超时时间
     * @return
     */
    public static RequestConfig defaultRequestConfig() {
        return RequestConfig.custom()
                .setConnectTimeout(50000)
                .setSocketTimeout(50000)
                .setConnectionRequestTimeout(3000).build();
    }

    public static FutureCallback<HttpResponse> generateFutureCallBack() {
        return new FutureCallback<HttpResponse>() {

            @Override
            public void completed(final HttpResponse result) {
            }

            @Override
            public void failed(Exception ex) {

            }

            @Override
            public void cancelled() {

            }
        };
    }

    public static HttpResponse doGetRequest(String url) throws IOException {
        return doGetRequest(url, 10000, 10000);
    }

    public static HttpResponse doGetRequest(String url, int socketTimeout, int connectTimeout) throws IOException {
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout)
                .setConnectTimeout(connectTimeout).build();
        return doGetRequest(url, requestConfig);
    }


    public static HttpResponse doGetRequest(String url, int socketTimeout, int connectTimeout, HttpHost httpProxyHost) throws IOException {
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout)
                .setConnectTimeout(connectTimeout).setProxy(httpProxyHost).build();
        return doGetRequest(url, requestConfig);
    }

    public static HttpResponse doGetRequest(String url, RequestConfig requestConfig) throws IOException {
        HttpClient httpClient = HttpClients.createDefault();
        LOGGER.info("Method: GET, Url： {}", url);
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("content-Type", "application/json;charset=UTF-8");
        httpGet.setConfig(requestConfig);
        return httpClient.execute(httpGet);
    }


    public static String postJsonData(String url, String token, String json) {
        String result = null;
        if (null == url) {
            return result;
        }
        try {
            HttpClient httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("content-Type", "application/json;charset=UTF-8");
            httpPost.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000)
                    .setConnectTimeout(60000).build();
            httpPost.setConfig(requestConfig);
            StringEntity stringEntity = new StringEntity(json, "UTF-8");
            httpPost.setEntity(stringEntity);
            HttpResponse response = httpClient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                result = EntityUtils.toString(response.getEntity(), "utf-8");
            }
            LOGGER.info("返回值是： {}, Response Status: {}", result, response.getStatusLine().getStatusCode());
        } catch (ConnectTimeoutException timeoutException) {
            LOGGER.error("调用外系统接口超时！", timeoutException);
        } catch (Exception e) {
            LOGGER.error("调用外系统接口错误！", e);
        }
        return result;
    }


    public static String putJsonData(String url, String token, String json){
        String result = null;
        if (null == url) {
            return result;
        }
        try {
            HttpClient httpClient = HttpClients.createDefault();
            HttpPut httpPut = new HttpPut(url);
            httpPut.setHeader("content-Type", "application/json;charset=UTF-8");
            httpPut.setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token);
            RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(60000)
                    .setConnectTimeout(60000).build();
            httpPut.setConfig(requestConfig);
            StringEntity stringEntity = new StringEntity(json, "UTF-8");
            httpPut.setEntity(stringEntity);
            HttpResponse response = httpClient.execute(httpPut);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                result = EntityUtils.toString(response.getEntity(), "utf-8");
                if (!Objects.equals(JSONObject.parseObject(result).getInteger("code") , HttpStatus.SC_OK)) {
                    LOGGER.error(JSONObject.parseObject(result).getString("code"));
                    for (Header header : response.getAllHeaders()) {
                        LOGGER.error(header.getName() + " : " + header.getValue());
                    }
                }
            }
            LOGGER.info("返回值是： {}, Response Status: {}", result, response.getStatusLine().getStatusCode());
        } catch (ConnectTimeoutException timeoutException) {
            LOGGER.error("调用外系统接口超时！", timeoutException);
        } catch (Exception e) {
            LOGGER.error("调用外系统接口错误！", e);
        }
        return result;
    }


}
